package com.ant.exceptions;

import com.ant.constant.ResultEnum;
import com.ant.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.io.IOException;
import java.nio.file.AccessDeniedException;

/**
 * 全局异常处理器
 * 
 * 统一处理应用中抛出的各种异常，将异常转换为标准的API响应格式
 * 使用@ControllerAdvice注解，对所有Controller的异常进行拦截处理
 * 确保API接口返回统一的错误响应格式，提升用户体验
 * 
 * @Auther: 灏
 * @Date: 2025/6/1 - 06 - 01 - 18:02
 * @Description: com.ant.infrastructure.exceptions
 * @version: 1.0
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
    
    /**
     * 处理资源未找到异常（404错误）
     * 
     * @param ex 资源未找到异常
     * @param request Web请求对象
     * @return 统一的错误响应
     */
    @ExceptionHandler(ResourceNotFoundException.class)
    public Result<String> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        Result<String> resultFailed = Result.failed(HttpStatus.NOT_FOUND.value(), HttpStatus.NOT_FOUND.getReasonPhrase(),request.getContextPath()+"资源未找到");
        log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }
    
    /**
     * 处理业务异常
     * 
     * @param ex 业务异常
     * @param request Web请求对象
     * @return 统一的错误响应
     */
    @ExceptionHandler(BizException.class)
    public Result<String> bizException(ResourceNotFoundException ex, WebRequest request) {
        Result<String> resultFailed = Result.failed(ResultEnum.SERVIC_EERROR.code(), ResultEnum.SERVIC_EERROR.message(),ex.getMessage());
        log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理运行时异常
     * 
     * @param ex 运行时异常
     * @return 统一的错误响应
     */
    @ExceptionHandler(RuntimeException.class)
    public Result<String> runtimeExceptionHandler(RuntimeException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.INTERNAL_SERVER_ERROR.code(),ResultEnum.INTERNAL_SERVER_ERROR.message(), ex.getMessage());
        log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理空指针异常
     * 
     * @param ex 空指针异常
     * @return 统一的错误响应
     */
    @ExceptionHandler(NullPointerException.class)
    public Result<String> nullPointerExceptionHandler(NullPointerException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.BODY_NOT_MATCH.code(),ResultEnum.BODY_NOT_MATCH.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理类型转换异常
     * 
     * @param ex 类型转换异常
     * @return 统一的错误响应
     */
    @ExceptionHandler(ClassCastException.class)
    public Result<String> classCastExceptionHandler(ClassCastException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.BODY_NOT_MATCH.code(),ResultEnum.BODY_NOT_MATCH.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理IO异常
     * 
     * @param ex IO异常
     * @return 统一的错误响应
     */
    @ExceptionHandler(IOException.class)
    public Result<String> iOExceptionHandler(IOException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.INTERNAL_SERVER_ERROR.code(), ResultEnum.INTERNAL_SERVER_ERROR.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理方法未找到异常
     * 
     * @param ex 方法未找到异常
     * @return 统一的错误响应
     */
    @ExceptionHandler(NoSuchMethodException.class)
    public Result<String> noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.BODY_NOT_MATCH.code(), ResultEnum.BODY_NOT_MATCH.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理数组越界异常
     * 
     * @param ex 数组越界异常
     * @return 统一的错误响应
     */
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public Result<String> indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.BODY_NOT_MATCH.code(), ResultEnum.BODY_NOT_MATCH.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理HTTP消息不可读异常（400错误）
     * 
     * @param ex HTTP消息不可读异常
     * @return 统一的错误响应
     */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public Result<String> requestNotReadable(HttpMessageNotReadableException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.BODY_NOT_MATCH.code(),ResultEnum.BODY_NOT_MATCH.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理类型不匹配异常（400错误）
     * 
     * @param ex 类型不匹配异常
     * @return 统一的错误响应
     */
    @ExceptionHandler({TypeMismatchException.class})
    public Result<String> requestTypeMismatch(TypeMismatchException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.BODY_NOT_MATCH.code(), ResultEnum.BODY_NOT_MATCH.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理服务器内部错误（500错误）
     * 
     * @param ex 运行时异常
     * @return 统一的错误响应
     */
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public Result<String> server500(RuntimeException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.INTERNAL_SERVER_ERROR.code(), ResultEnum.INTERNAL_SERVER_ERROR.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理栈溢出错误
     * 
     * @param ex 栈溢出错误
     * @return 统一的错误响应
     */
    @ExceptionHandler({StackOverflowError.class})
    public Result<String> requestStackOverflow(StackOverflowError ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.INTERNAL_SERVER_ERROR.code(),ResultEnum.INTERNAL_SERVER_ERROR.message(), ex.getMessage());
        log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理算术异常（如除零错误）
     * 
     * @param ex 算术异常
     * @return 统一的错误响应
     */
    @ExceptionHandler({ArithmeticException.class})
    public Result<String> arithmeticException(ArithmeticException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.INTERNAL_SERVER_ERROR.code(), ResultEnum.INTERNAL_SERVER_ERROR.message(), ex.getMessage());
       log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理其他未捕获的异常
     * 
     * @param ex 通用异常
     * @return 统一的错误响应
     */
    @ExceptionHandler({Exception.class})
    public Result<String> exception(Exception ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.INTERNAL_SERVER_ERROR.code(), ResultEnum.INTERNAL_SERVER_ERROR.message(), ex.getMessage());
        log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理权限拒绝异常
     * 
     * @param ex 权限拒绝异常
     * @return 统一的错误响应
     */
    @ExceptionHandler({AccessDeniedException.class})
    public Result<String> handleAccessDeniedException(AccessDeniedException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.SIGNATURE_NOT_MATCH.code(), ResultEnum.SIGNATURE_NOT_MATCH.message(), ex.getMessage());
        log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }

    /**
     * 处理参数验证失败异常
     * 
     * @param ex 方法参数验证失败异常
     * @return 统一的错误响应
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Result<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        Result<String> resultFailed = Result.failed(ResultEnum.BODY_NOT_MATCH.code(), ResultEnum.BODY_NOT_MATCH.message(), ex.getMessage());
        log.error(ex.toString());
        ex.printStackTrace();
        return resultFailed;
    }
}
